package br.com.lucasddaniel.inbuzios.dao;

import java.util.Enumeration;
import java.util.Hashtable;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDiskIOException;
import android.database.sqlite.SQLiteOpenHelper;

/** Classe para persistencia. */
public class TuristaAdaptadorBanco {

    private static DatabaseHelper dbHelper;
    private static SQLiteDatabase db;

    /** Classe de ajuda de acesso ao banco */
    private static class DatabaseHelper extends SQLiteOpenHelper {
        DatabaseHelper(Context context) {
            super(context, TuristaEsquemaBanco.DATA_BASE_NAME, null, TuristaEsquemaBanco.CURRENT_DATABASE_VERSION);
        }

        @Override
        public void onCreate(SQLiteDatabase db) {
            db.execSQL(TuristaEsquemaBanco.SQL_CREATE_TABLE);
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        }
    }

    /**
     * Abre conexao com o banco.
     * 
     * @param context
     * @throws ExcessaoBanco
     */
    public static void abre(Context context) throws ExcessaoBanco {
        try {
            dbHelper = new DatabaseHelper(context);
            db = dbHelper.getWritableDatabase();
        } catch (SQLException sqle) {
            throw new ExcessaoBanco(sqle.getMessage(), ExcessaoBanco.DATABASE_OPEN_FAIL);
        }
    }

    /**
     * Fecha conexao com o banco.
     * 
     * @param context
     * @throws ExcessaoBanco
     */
    public static void fecha(boolean force) throws ExcessaoBanco {
        if (!force && !db.isOpen()) {
            throw new ExcessaoBanco("Banco fechado", ExcessaoBanco.DATABASE_NOT_OPEN);
        }
        if (dbHelper != null) {
            dbHelper.close();
        }
        dbHelper = null;
        db = null;
    }

    /**
     * Consulta estado de conexao com o banco.
     * 
     */
    public static boolean estaAberto() {
        return (dbHelper != null && db != null && db.isOpen());
    }

    /**
     * Insere Turista.
     * 
     * @param table
     * @param initialValues
     * @return
     * @throws ExcessaoBanco
     */
    public static int insere(String table, ContentValues initialValues) throws ExcessaoBanco {
        try {
            long id = db.insertOrThrow(table, null, initialValues);
            if (id == -1) {
                throw new ExcessaoBanco("Nao conseguiu inserir o objeto na tabela '" + table + "'", ExcessaoBanco.DATABASE_INSERT_FAIL);
            }
            return (int) id;
        } catch (SQLiteDiskIOException diskIOException) {
            throw new ExcessaoBanco("Memoria insuficiente pra criar o item.", ExcessaoBanco.INSUFFICIENT_MEMORY);
        }
    }

    /**
     * Atualiza Turista.
     * 
     * @param table
     * @param values
     * @param idColumnValue
     * @throws ExcessaoBanco
     */
    public static void atualiza(String table, ContentValues values, String idColumnValue) throws ExcessaoBanco {
        try {
            long id = TuristaAdaptadorBanco.db.update(table, values, "id=?", new String[] {idColumnValue});
            if (id != 1) {
                throw new ExcessaoBanco("Nao foi possivel atualizar o objeto na tabela '" + table + "'", ExcessaoBanco.DATABASE_UPDATE_FAIL);
            }
        } catch (SQLiteDiskIOException diskIOException) {
            throw new ExcessaoBanco("Memoria insuficiente para criar ou copiar itens.", ExcessaoBanco.INSUFFICIENT_MEMORY);
        }
    }

    /**
     * Recupera os itens da base utilizando clausula where.
     * 
     * @param table
     * @param filters
     * @return
     * @throws ExcessaoBanco
     */
    public static Cursor getObjects(String table, Hashtable<String, String> filters) throws ExcessaoBanco {
        Cursor cursorResult = null;
        String[] filterValues = new String[filters.size()];
        String whereClause = TuristaAdaptadorBanco.createWhereClause(filters, null, filterValues);
        cursorResult = db.query(table, null, whereClause, filterValues, null, null, TuristaEsquemaBanco.TABLE_COLUMNS[8].columnName + " , " + TuristaEsquemaBanco.TABLE_COLUMNS[4].columnName + " ASC");

        return cursorResult;
    }

    /**
     * Apaga tabela ao exportar dados por regra de neg�cio.
     * 
     * @throws ExcessaoBanco
     */
    public static void apagarDadosTuristasCadastrados() throws ExcessaoBanco {
        try {
            db.execSQL("DELETE FROM " + TuristaEsquemaBanco.TABLE_NAME);
        } catch (SQLiteDiskIOException diskIOException) {
            throw new ExcessaoBanco("Memoria insuficiente para criar ou copiar itens.", ExcessaoBanco.INSUFFICIENT_MEMORY);
        }
    }

    /**
     * Clausula where.
     * 
     * @param filters
     * @param tablePrefix
     * @param filterValues
     * @return
     */
    private static String createWhereClause(Hashtable<String, String> filters, String tablePrefix, String[] filterValues) {
        String whereClause = null;
        if (tablePrefix == null) {
            tablePrefix = "";
        }
        if (filters.size() > 0) {
            whereClause = "";
            Enumeration<String> filterFields = filters.keys();
            int i = 0;
            while (filterFields.hasMoreElements()) {
                String field = filterFields.nextElement();
                if (whereClause.length() > 0) {
                    whereClause += " AND ";
                }
                whereClause += tablePrefix + field + " == ?";
                filterValues[i] = filters.get(field);
                i++;
            }
        }
        return whereClause;
    }
}
